/**
 *
 */
package org.cmcc.pcap.packet.capture;


import java.io.File;
import java.lang.Thread.State;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.jdbc.core.JdbcTemplate;

import com.cmcc.xdr.util.ProtocolSpringContextUtils;
import com.google.common.collect.Lists;

/**
 * @Date 2018年8月7日 上午10:10:44
 * @author Amish
 *
 */
public class TaskContext {
	private static Logger logger = LogManager.getLogger(TaskContext.class);
//	private static JdbcTemplate jdbcTemplate;
	
	private String taskId;
	private String pcapDir;
	
	private int pcapDealThreads = 1;
	private int realPcapDealThreads = 1;
	
	private long dealTotalBytes = 0;
	private long totalBytes = 0;
	private Thread[] threads;
	
	private boolean terminated = false;
	
//	static {
//		ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/applicationContext.xml"); //
//		jdbcTemplate = (JdbcTemplate)ctx.getBean("jdbcTemplate");
//	}
	
	
	public TaskContext(String taskId,String pcapDir){
		this.taskId = taskId;
		this.pcapDir = pcapDir;
		this.pcapDealThreads = 2;//PacketAnalysisConfig.getConfigAsInt("pcap.deal.threads") > 0 ? PacketAnalysisConfig.getConfigAsInt("pcap.deal.threads") : 1;
	}
	
	public void analysisStart(){
		File dir = new File(pcapDir);
		if( !dir.isDirectory() ){
			logger.error("the input is not a directory ");
			return;
		}
		
		File[] files = dir.listFiles(PacketAnalysis.filenameFilter);
		
		logger.info("the fileNumber is : "+files.length);
		//logger.info("the dir total length is : "+dir.length());//8192
		
		totalBytes = 0;
		for(File file : files){
			totalBytes += file.length();
			//logger.info("the < "+file.getName()+" > file.lentgh is : "+file.length());
		}
		logger.info("the dir total length is : "+totalBytes);
		
		if(pcapDealThreads <= 1 ){
			realPcapDealThreads = 1;
		}else if(pcapDealThreads > files.length){
			realPcapDealThreads = files.length;//保证线程数不能大于文件数
		}else{
			realPcapDealThreads = pcapDealThreads;
		}
		logger.info("the real pacp deal threads is : "+realPcapDealThreads);

		List<File> listFiles = new ArrayList<File>(Arrays.asList(files));
		
		
		int partitionSize = listFiles.size();
		if(listFiles.size() % realPcapDealThreads > 0){
			partitionSize = listFiles.size() / realPcapDealThreads + 1;
		}else if(listFiles.size() % realPcapDealThreads == 0){
			partitionSize = listFiles.size() / realPcapDealThreads;
		}
		
		List<List<File>> subLists = Lists.partition(listFiles, partitionSize);// 利用Lists拆分数组,这里的partitionSize表示分隔后的List元素最大个数
		
		threads = new Thread[realPcapDealThreads];
		for(int i=0;i<threads.length;i++){
			//File[] subFiles = (File[])((List<File>)subLists.get(i)).toArray();
			List<File> subList = subLists.get(i);
			logger.info("pcapDealThread <"+i+"> contains files :"+subList.size()+". file list : "+subList.toString());
			
			PcapDealThread pcapDealThread = new PcapDealThread(taskId,subList,this);
			threads[i] = new Thread(pcapDealThread);
			threads[i].setDaemon(true);
			threads[i].start();	
		}

		
		while(!terminated){//此处脑子是混乱的
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				logger.error(e.getCause(),e);
			}
			boolean threadsState = true;
			for(Thread thread : threads){
				boolean subThreadState =  thread.getState().equals(State.TERMINATED)? true : false;
				threadsState = threadsState & subThreadState;
			}
			terminated = threadsState;
		}
		logger.info("all pcap analysis done ");
	}
	
	public synchronized void updateInfo(String taskId,long dealBytes){
		JdbcTemplate jdbcTemplate = new JdbcTemplate(ProtocolSpringContextUtils.getBean("dataSource"));
		dealTotalBytes = dealTotalBytes + dealBytes;
		String proportion = PacketAnalysis.proportionCalculation(dealTotalBytes,totalBytes);
		//将处理进度写入数据库 
		StringBuffer sql = new StringBuffer();
		sql.append("UPDATE STAT_TASKINFO SET  UNPACK_PROCESS_PERCENT= '");
		sql.append(proportion);
		sql.append("' WHERE ID = '");
		sql.append(taskId+"'" );
		try {
			jdbcTemplate.execute(sql.toString());
			logger.info("complete : "+ dealTotalBytes +"/ total : "+totalBytes);
			logger.info("the pcap deal rate of progress is : "+ proportion +" %");
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("解析数据包进度更新失败!",e);
		}
	}
	
	class PcapDealThread implements Runnable{
        String taskId;
        //File[] files;
        List<File> subList;
        TaskContext tc;
        public PcapDealThread(String taskId, List<File> subList, TaskContext tc){
        	this.taskId = taskId;
        	this.subList = subList;
        	this.tc = tc;
        }
        
		@Override
		public void run() {
			try{
				JCaptures jc = new JCaptures(taskId);  //赋值标准id,存入数据库表中
				//long dealTotalBytes = 0;
				for(File file : subList){//TODO file 分组 分给多个jcpatures处理？
					logger.info("the < "+file.getName()+" > file.lentgh is : "+file.length());
					long dealBytes = file.length();
					
//					jc.complete = false;
					jc.tcp_complete = false;
					jc.udp_complete = false;
					
					jc.captureFromFile(file.getAbsolutePath(),null);
					
					tc.updateInfo(taskId,dealBytes);//更新处理完的数据
				}
				
				jc.stop();//显示调用stop，否则文件处理完也不会结束进程
			}catch(Exception e){
				logger.error(e.getCause(),e);
			}
		}
		
	}
	
}